/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package merlion.frm.bpm.session;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import merlion.crm.sopm.entity.ItemLine;
import merlion.frm.bpm.entity.CustomerPaymentRecord;
import merlion.frm.bpm.entity.Invoice;
import merlion.frm.bpm.entity.Receipt;
import merlion.scm.lcm.entity.DeliveryOrder;

/**
 *
 * @author Yuwei
 */
@Stateless
public class SalesBPSessionBean implements SalesBPSessionBeanLocal {

    @PersistenceContext
    private EntityManager entityManager;
    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")

    @Override
    public String generateInvoiceId() {
        //Get date YYYYMMDD
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String frontId = sdf.format(cal.getTime());

        //Query SalesOrder table, anything like 'yyMMdd'
        Query query = entityManager.createQuery("SELECT i FROM Invoice i WHERE i.invoiceId LIKE :p1");
        query.setParameter("p1", "%" + frontId + "%");

        //Get result size
        int size = query.getResultList().size() + 1;
        String backId = String.format("%04d", size);

        //Set new ID to 'YYYYMMDD' + 'size + 1'
        String id = "IN" + frontId + "/" + backId;
        //return id
        return id;
    }

    @Override
    public String generateCustomerPaymentRecordId() {
        //Get date YYYYMMDD
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String frontId = sdf.format(cal.getTime());

        //Query SalesOrder table, anything like 'yyMMdd'
        Query query = entityManager.createQuery("SELECT c FROM CustomerPaymentRecord c WHERE c.customerPaymentRecordId LIKE :p1");
        query.setParameter("p1", "%" + frontId + "%");

        //Get result size
        int size = query.getResultList().size() + 1;
        String backId = String.format("%04d", size);

        //Set new ID to 'YYYYMMDD' + 'size + 1'
        String id = "CPR" + frontId + "/" + backId;
        //return id
        return id;
    }

    @Override
    public String generateReceiptId() {
        //Get date YYYYMMDD
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String frontId = sdf.format(cal.getTime());

        //Query SalesOrder table, anything like 'yyMMdd'
        Query query = entityManager.createQuery("SELECT r FROM Receipt r WHERE r.receiptId LIKE :p1");
        query.setParameter("p1", "%" + frontId + "%");

        //Get result size
        int size = query.getResultList().size() + 1;
        String backId = String.format("%04d", size);

        //Set new ID to 'YYYYMMDD' + 'size + 1'
        String id = "RE" + frontId + "/" + backId;
        //return id
        return id;
    }

    @Override
    public String generateSupplierPaymentRecordId() {
        //Get date YYYYMMDD
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String frontId = sdf.format(cal.getTime());

        //Query SalesOrder table, anything like 'yyMMdd'
        Query query = entityManager.createQuery("SELECT s FROM SupplierPaymentRecord s WHERE s.invoiceNo LIKE :p1");
        query.setParameter("p1", "%" + frontId + "%");

        //Get result size
        int size = query.getResultList().size() + 1;
        String backId = String.format("%04d", size);

        //Set new ID to 'YYYYMMDD' + 'size + 1'
        String id = "SPR" + frontId + "/" + backId;
        //return id
        return id;
    }

    @Override
    public Invoice createInvoice(DeliveryOrder deliveryOrder) {
        System.out.println("deliveryOrder id: " + deliveryOrder.getId());
        deliveryOrder = (DeliveryOrder) entityManager.createQuery("SELECT do FROM DeliveryOrder do WHERE do.id = " + deliveryOrder.getId()).getSingleResult();
        Invoice invoice = new Invoice();
        invoice.setCustomerPaymentRecord(null);
        invoice.setInvoiceDate(new Timestamp(System.currentTimeMillis()));
        invoice.setInvoiceDateStr(invoice.getInvoiceDate().toString());
        invoice.setDeliveryOrder(deliveryOrder);
        invoice.setCustomer(deliveryOrder.getSalesOrder().getCustomer());
        invoice.setPaid(false);
        invoice.setPoNumber(deliveryOrder.getSalesOrder().getPurchaseOrder().getPoNumber());
        invoice.setInvoiceId(generateInvoiceId());
        invoice.setCashInAdvance(deliveryOrder.getSalesOrder().getPaymentMode());
        invoice.setSubtotal(deliveryOrder.getSubtotal());
        invoice.setTax(deliveryOrder.getTax());
        invoice.setTotal(deliveryOrder.getTotal());

        //set due date
        long oneDay = (long) (1 * 24 * 60 * 60 * 1000);
        long extensionPeriod = invoice.getCustomer().getCreditAccount().getCreditGroup().getExtensionDays() * oneDay;
        invoice.getInvoiceDueDate().setTime(invoice.getInvoiceDate().getTime() + extensionPeriod);

        if (invoice.getDeliveryOrder().getSalesOrder().getPaymentMode().booleanValue() == Boolean.FALSE) {//Credit Purchase
            //Update customer's credit balance;
            double creditBalance = invoice.getCustomer().getCreditAccount().getCreditBalance();

            invoice.getCustomer().getCreditAccount().setCreditUsed(invoice.getCustomer().getCreditAccount().getCreditUsed() + invoice.getDeliveryOrder().getTotal());
            creditBalance = creditBalance - invoice.getDeliveryOrder().getTotal();
            invoice.getCustomer().getCreditAccount().setCreditBalance(creditBalance);
        } else {
            //Pay Cash In advance
        }
        return invoice;
    }

    @Override
    public Invoice saveInvoice(Invoice invoice) {
        invoice.getDeliveryOrder().setInvoice(invoice);
        if(invoice.getDeliveryOrder().getSalesOrder().getPaymentMode()==Boolean.FALSE){
            invoice.getDeliveryOrder().getShippingOrder().setInvoiced(Boolean.TRUE);
        }
        
        entityManager.merge(invoice);
        entityManager.flush();
        return invoice;
    }

    @Override
    public Collection<Invoice> getAllInvoice() {
        return entityManager.createQuery("SELECT i FROM Invoice i").getResultList();
    }

    @Override
    public CustomerPaymentRecord saveCustomerPaymentRecord(CustomerPaymentRecord cpr) {
        //TODO: save cpr on database. have to check entity relations if it is correct
        Invoice i = cpr.getInvoice();
        cpr = entityManager.merge(cpr);
        i.setCustomerPaymentRecord(cpr);
        entityManager.merge(i);

        if (cpr.getCashInAdvance()) {//Cash in advance
            //save as cash in advance payment
        } else {//credit purchase
            Double paidAmount = cpr.getPaymentAmount();
            //Update credit Balance
            double creditBalance = cpr.getInvoice().getCustomer().getCreditAccount().getCreditBalance();
            cpr.getInvoice().getCustomer().getCreditAccount().setCreditUsed(cpr.getInvoice().getCustomer().getCreditAccount().getCreditUsed() - paidAmount);
            creditBalance = creditBalance + paidAmount;
            cpr.getInvoice().getCustomer().getCreditAccount().setCreditBalance(creditBalance);
        }

        return entityManager.merge(cpr);
    }

    @Override
    public Receipt saveReceipt(Receipt receipt) {
        //TODO: save receipt on database. have to check entity relations if it is correct
        return entityManager.merge(receipt);
    }

    @Override
    public Collection<CustomerPaymentRecord> getAllCustomerPaymentRecord() {
        return entityManager.createQuery("SELECT cpr FROM CustomerPaymentRecord cpr").getResultList();
    }

    @Override
    public Collection<Receipt> getAllReceipt() {
        return entityManager.createQuery("SELECT r FROM Receipt r").getResultList();
    }

    @Override
    public Collection<Invoice> getAllUnpaidInvoice() {
        return entityManager.createQuery("SELECT i FROM Invoice i WHERE i.customerPaymentRecord IS NULL").getResultList();
    }
    
    @Override
    public DeliveryOrder getDeliveryOrderById(Long id){
        return (DeliveryOrder)entityManager.createQuery("SELECT d FROM DeliveryOrder d WHERE d.id = " + id).getResultList().get(0);
    }
    
    @Override
    public Invoice getInvoiceById(Long invoiceId){
//        Query query = entityManager.createQuery("SELECT i FROM Invoice i WHERE i.id =:p1");
//        query.setParameter("p1", invoiceId);
//        System.out.println("SalesBPSessionBean");
//        return (Invoice) query.getResultList().get(0);
        return entityManager.find(Invoice.class, invoiceId);
    }
    
    @Override
    public void refund(CustomerPaymentRecord cpr){
        cpr.setRefunded(Boolean.TRUE);
        entityManager.merge(cpr);
        entityManager.flush();
    }
}
